
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>5、线程池 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>5、线程池 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">为什么在编程中推荐使用线程池，而不是在需要时才创建新线程？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为线程是稀缺资源，如果无限制地创建，会消耗大量系统资源，甚至导致服务器卡顿或宕机。线程池通过统一管理和复用线程，可以控制运行的线程数量，将超出处理能力的任务放入队列中排队，从而有效控制资源消耗并保证系统稳定。</div>
          </div>
          <div class="card-source">来源: 为什么要使用线程池？</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">使用线程池能带来哪三个主要好处？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. 降低资源消耗：通过重复利用已创建的线程，减少了线程创建和销毁造成的消耗。<br>2. 提高响应速度：任务到达时，可以直接使用池中的线程执行，无需等待线程创建。<br>3. 提高线程的可管理性：可以对线程进行统一的分配、监控和调优，提高系统稳定性。</div>
          </div>
          <div class="card-source">来源: 使用线程池的好处</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在创建`ThreadPoolExecutor`时，`corePoolSize`和`maximumPoolSize`这两个核心参数有何区别？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`corePoolSize`指的是线程池中保持的核心线程数量，这些线程即使空闲也不会被回收。而`maximumPoolSize`是线程池允许容纳的最大线程数。只有当核心线程都在工作且工作队列（workQueue）也满了之后，线程池才会创建新的线程，直到总数达到`maximumPoolSize`。</div>
          </div>
          <div class="card-source">来源: 线程池7大核心参数</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">当一个新任务提交给线程池时，其完整的处理流程是怎样的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. 首先判断当前运行的线程数是否小于`corePoolSize`，如果是，则创建新线程来执行任务。<br>2. 如果线程数已达到`corePoolSize`，则将任务放入工作队列`workQueue`。<br>3. 如果工作队列已满，但当前线程数小于`maximumPoolSize`，则创建新的非核心线程来执行任务。<br>4. 如果工作队列已满，且线程数也达到了`maximumPoolSize`，则根据设定的拒绝策略来处理该任务。</div>
          </div>
          <div class="card-source">来源: 线程池的任务调度</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">如何根据任务是“CPU密集型”还是“I/O密集型”来合理设置线程池的核心线程数？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">对于CPU密集型任务，为了减少不必要的上下文切换开销，核心线程数通常设置为“CPU核心数 + 1”。对于I/O密集型任务，由于线程会因等待I/O而阻塞，可以设置更多的线程以充分利用CPU，核心线程数通常设置为“CPU核心数 * 2”。</div>
          </div>
          <div class="card-source">来源: 线程池核心数的设置</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">当线程池无法处理新任务时会触发拒绝策略，请描述文档中提到的四种拒绝策略。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. AbortPolicy：默认策略，直接抛出异常。<br>2. DiscardPolicy：直接丢弃任务，不作任何处理。<br>3. DiscardOldestPolicy：丢弃任务队列中最旧的一个任务。<br>4. CallerRunsPolicy：将任务交由提交任务的那个线程（调用execute方法的线程）来同步执行。</div>
          </div>
          <div class="card-source">来源: 拒绝策略</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">线程池的`shutdown`和`stop`这两种运行状态有什么关键区别？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`shutdown`状态（通过调用`shutdown()`方法进入）表示线程池不再接受新任务，但会继续处理队列中已存在的任务。而`stop`状态（通过调用`shutdownNow()`方法进入）则更激进，它不仅不接受新任务，还会清空队列里的任务，并尝试中断所有正在执行的任务。</div>
          </div>
          <div class="card-source">来源: 线程池的运行状态</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">作为线程池的工作队列，`LinkedBlockingQueue`与`ArrayBlockingQueue`在锁机制和并发性能上有何主要不同？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">主要区别在于锁的实现。`ArrayBlockingQueue`的添加和移除操作共用同一个锁，导致生产者和消费者无法真正并行。而`LinkedBlockingQueue`使用分离锁（putLock和takeLock），允许生产者和消费者在高并发场景下并行操作，因此通常具有更高的吞吐量和并发性能。</div>
          </div>
          <div class="card-source">来源: 线程池工作队列 (LinkedBlockingQueue和ArrayBlockingQueue区别)</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在`ThreadPoolExecutor`中，`keepAliveTime`参数的作用是什么？它对哪类线程生效？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`keepAliveTime`参数定义了空闲线程的存活时间。它只对超过`corePoolSize`数量的“临时线程”生效。当线程池中的线程数大于`corePoolSize`时，如果一个线程空闲时间超过了`keepAliveTime`，它就会被回收，直到线程池的线程数量缩减回`corePoolSize`。</div>
          </div>
          <div class="card-source">来源: 线程池7大核心参数</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
